package org.itboys.mobile.service.mysql.mobile.pay;

import org.apache.commons.lang3.StringUtils;
import org.itboys.commons.ErrorException;
import org.itboys.commons.utils.tools.ListUtil;
import org.itboys.mobile.common.SundayCommonConstants;
import org.itboys.mobile.dao.order.MdlOrderMapper;
import org.itboys.mobile.dao.pay.SundayPayConfigMapper;
import org.itboys.mobile.dto.pay.SundayPayDto;
import org.itboys.mobile.entity.mongo.SundayCid;
import org.itboys.mobile.entity.mongo.SundayMember;
import org.itboys.mobile.entity.mysql.order.MdlOrder;
import org.itboys.mobile.entity.mysql.pay.SundayPay;
import org.itboys.mobile.entity.mysql.pay.SundayPayConfig;
import org.itboys.mobile.service.mongo.mobile.member.SundayMobileMemberService;
import org.itboys.mobile.service.mongo.web.member.SundayMemberService;
import org.itboys.mobile.service.mysql.mobile.income.MdlMobileIncomeService;
import org.itboys.mobile.util.NumberUtil;
import org.itboys.mongodb.service.BaseMySqlService;
import org.itboys.pay.alipay.AlipayMobileService;
import org.itboys.pay.alipay.AlipayWapResult;
import org.itboys.pay.tools.XMLUtil;
import org.itboys.pay.weixin.AppPaySignTool;
import org.itboys.pay.weixin.WXPayNotify;
import org.itboys.pay.weixin.WeixinPayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.DataInputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * 作者：zzq
 * 时间：2017/12/6
 * 描述：迈迪龙_支付
 */
@Service
public class SundayMobilePayService extends BaseMySqlService<SundayPay>{

    public static String PAY_CALLBACK_URL_alipay= "http://mobile.mdl.com/sunday/mobile/pay/callback/alipay";
    public static String PAY_CALLBACK_URL_wechat= "http://mobile.mdl.com/sunday/mobile/pay/callback/wechat";
    @Autowired
    private MdlOrderMapper orderMapper;
    @Autowired
    private SundayPayConfigMapper payConfigMapper;
    @Autowired
    private SundayMobileMemberService memberService;
    @Autowired
    private MdlMobileIncomeService incomeService;
    public SundayPayDto preparePay(Integer payType, List<Long> orderIds, Integer type){
        //1,声明返回结果
        SundayPayDto payDto =null;
        //传入第三方的外部订单号
        String orderNo= NumberUtil.generateNumber("PREPAY");
        //支付描述
        String remark="订单消费";
        //本次需要支付的金额
        Double payAmount=0.00;
        //本次需要操作的订单（余额充值记录）ids
        StringBuilder orderIdsStr = new StringBuilder();
        Map<String,Object> param = new HashMap<String,Object>();
        param.clear();
        param.put("ids",orderIds);
        List<MdlOrder> orders = orderMapper.select(param);
        for(MdlOrder order:orders){
            //logger.info("-----订单编号"+order.getOrderNo()+",实付金额="+order.getPayAmount());
            payAmount+=order.getPayAmount().doubleValue();
            //存放需要订单ID时，用_隔开;
            orderIdsStr.append(order.getId()+"_");
        }
        //4，返回移动端需要的支付参数
        param.clear();
        SundayPayConfig payConfig =null;
        List<SundayPayConfig> payConfigs =payConfigMapper.select(param);
        //4.1,返回支付宝参数
        if(payType==SundayCommonConstants.pay_type_alipay){
            for(SundayPayConfig p:payConfigs){
                if(p.getType()== SundayCommonConstants.pay_type_alipay){
                    payConfig=p;
                }
            }
            if(payConfig==null){
                throw new ErrorException("预支付失败，支付宝未配置支付信息");
            }
            String alipayResult =null;
            try {
                //获取平台的支付宝PID
                //商户私钥
                String alipayAppPrivatekey=payConfig.getAlipayAppPrivateKey();
                logger.info("--支付宝商户私钥--"+alipayAppPrivatekey);
                //商户公钥
                String alipayAppPublicKey=payConfig.getAlipayAppPublicKey();
                logger.info("--支付宝商户公钥--"+alipayAppPublicKey);
                alipayResult= AlipayMobileService.newAppPay(
                        payConfig.getAlipayAppId(),payAmount.toString(),orderNo,
                        PAY_CALLBACK_URL_alipay,alipayAppPrivatekey,
                        remark, remark, alipayAppPublicKey);
                //AlipayMobileService.t
            } catch (Exception e) {
                logger.info("预支付，支付宝，内部组装参数错误");
                e.printStackTrace();

            }


            payDto=new SundayPayDto(orderNo, payAmount.toString(),remark,alipayResult );

        }else if(payType==SundayCommonConstants.pay_type_wechatpay_open){
            for(SundayPayConfig p:payConfigs){
                if(p.getType()== SundayCommonConstants.pay_type_wechatpay_open){
                    payConfig=p;
                }
            }
            if(payConfig==null){
                throw new ErrorException("预支付失败，支付宝未配置支付信息");
            }
            //WeixinPaySignTool tool=null;
            AppPaySignTool tool=null;
            try {
			/*	tool=WeixinPayUtils.paySign(String appid, String mchId,
						String openid, String outTradeNo,
						String spbillCreateIp, String tradeType, String body,
						String totalFee, String notifyUrl, String productId, String ke)*/

                String payAmountStr=String.valueOf(new BigDecimal(payAmount*100).setScale(0,BigDecimal.ROUND_HALF_UP));
                //	logger.info("---实付金额222222222222--"+payAmountStr);
				/*tool=WeixinPayUtils.paySign(
						payConfig.getWeChatAppId(),
						payConfig.getWeChatMchId(),
						null,
						orderNo,
						"139.196.150.224",
						"APP",
						remark,
						payAmountStr,
						PAY_CALLBACK_URL_wechat,
						"1",
						payConfig.getWeChatApi());*/

                tool= WeixinPayUtils.appPay(payConfig.getWeChatAppId(),
                        payConfig.getWeChatMchId(),
                        orderNo, 	"139.196.150.224",
                        "APP", payAmountStr,PAY_CALLBACK_URL_wechat, payConfig.getWeChatApi());
                //logger.info("--支付-微信-tool"+tool);
                //return tool;




                payDto=new SundayPayDto(
                        orderNo,payAmountStr, remark,
                        tool.getAppid(), tool.getTimestamp(), tool.getNoncestr(),tool.getSign(),
                        "Sign=WXPay", "MD5",payConfig.getWeChatMchId(),tool.getPrepayid());

            } catch (Exception e) {
                e.printStackTrace();
                throw new ErrorException("微信预支付失败");
            }
        //线下支付
        }else if(payType==SundayCommonConstants.pay_type_line){
            for(MdlOrder order:orders){
                //避免重复回掉
                if(order.getOrderStatus()==SundayCommonConstants.ORDER_STATUS_DFK) {
                    logger.info("支付-支付宝-回掉-当前支付订单" + order.getOrderNo());
                    //order.setOrderStatus(SundayCommonConstants.ORDER_STATUS_DPS);
                    //order.setPayTime(new Date());
                    order.setPayNo("线下支付，暂无订单支付编号");
                    order.setPayType(SundayCommonConstants.pay_type_line);
                    order.setLinePayAmount(new BigDecimal(payAmount));
                    orderMapper.update(order);
                    //memberIds.add(order.getShopId());
                }
            }
            payDto=new SundayPayDto(orderNo, payAmount.toString(),remark,"" );
        }
        //5，本地存储预支付的结果，便于第三方支付回掉时执行业务逻辑
        SundayPay pay = new SundayPay(orderNo,orderIdsStr.substring(0,orderIdsStr.length()-1).toString(),
                new BigDecimal(payAmount).setScale(2,BigDecimal.ROUND_HALF_UP),type,remark);
        super.insert(pay);

        return payDto;
    }

    /**
     * 支付宝回调
     * @param request
     * @return
     */
    @Transactional
    public AlipayWapResult callback_alipay(HttpServletRequest request){
        AlipayWapResult alipayWapResult=new AlipayWapResult();
        //1，检验签名和请求来源
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("type",SundayCommonConstants.pay_type_alipay);
        List<SundayPayConfig> payConfigs =payConfigMapper.select(param);
        //支付宝公钥
        String publicKey = "";
        if(ListUtil.isNull(payConfigs)){
            return alipayWapResult;
        }
        //支付宝公钥
        publicKey=payConfigs.get(0).getAlipayPublicKey();
        logger.info("--支付宝公钥--"+publicKey);
        try {
            alipayWapResult =AlipayMobileService.notifyResult(request,publicKey);
        }catch (Exception e){
            e.printStackTrace();
            logger.info("支付-支付宝-回掉-签名验证错误。"+e);
            return alipayWapResult;
        }
        //验证成功或失败的标识
        boolean  verify_result= alipayWapResult.isVerify_result();
        String  trade_status=alipayWapResult.getTrade_status();
        String  out_trade_no=alipayWapResult.getOut_trade_no();
        String trade_no = alipayWapResult.getTrade_no();
        String notify_data=alipayWapResult.getNotify_data();
        BigDecimal  price =alipayWapResult.getPrice();
        logger.info("支付-支付宝-回掉-信息.trade_status="+trade_status+
                ",out_trade_no="+out_trade_no+
                ",trade_no="+trade_no+
                ",notify_data="+notify_data+
                ",price="+price+
                ",verify_result="+verify_result);
        if(!verify_result){
            logger.error("支付-支付宝-回掉-签名验证失败。");
            return alipayWapResult;
        }
        //查询本地预支付记录
        param.clear();
        if(StringUtils.isEmpty(out_trade_no)){
            logger.error("支付-支付宝-open-回掉-外部订单为空");
            alipayWapResult.setVerify_result(false);
            return alipayWapResult;
        }
        param.put("orderNo",out_trade_no);
        List<SundayPay> pays = super.select(param);
        if(ListUtil.isNull(pays)){
            logger.error("支付-支付宝-回掉-本地无预支付记录，返回");

            alipayWapResult.setVerify_result(false);
            return alipayWapResult;
        }
        SundayPay pay=pays.get(0);
        //2，项目内部逻辑。校验支付金额
        //2.1,订单消费
            List<Long> orderIds = new ArrayList<Long>();
            for(String orderIdStr:pay.getOrderIds().split("_")){
                orderIds.add(Long.valueOf(orderIdStr));
            }
            if(ListUtil.isNull(orderIds)){
                logger.error("支付-支付宝-回掉-本地预支付记录无订单参数，返回");
                alipayWapResult.setVerify_result(false);
                return alipayWapResult;
            }
            param.clear();
            param.put("status",SundayCommonConstants.ORDER_STATUS_DFK);
            param.put("ids",orderIds);
            List<MdlOrder> orders =orderMapper.select(param);
            //校验付款金额
            Double orderPayAmount = 0.00;
            for(MdlOrder order:orders){
                orderPayAmount+=order.getPayAmount().doubleValue();
            }
            if(price.compareTo(new BigDecimal(orderPayAmount).setScale(2,BigDecimal.ROUND_HALF_UP))==-1){
                logger.error("支付-支付宝-回掉-订单实际支付金额错误，应支付金额="+orderPayAmount+"，实际支付金额="+price+","+"预支付订单编号="+out_trade_no);
                alipayWapResult.setVerify_result(false);
                return alipayWapResult;
            }
            //更改订单状态
            List<Long> memberIds =new ArrayList<Long>();
            for(MdlOrder order:orders){
                //避免重复回掉
                if(order.getOrderStatus()==SundayCommonConstants.ORDER_STATUS_DFK) {
                    logger.info("支付-支付宝-回掉-当前支付订单" + order.getOrderNo());
                    order.setOrderStatus(SundayCommonConstants.ORDER_STATUS_DPS);
                    order.setPayTime(new Date());
                    order.setPayNo(trade_no);
                    order.setPayType(2);
                    order.setAliPayAmount(price);
                    orderMapper.update(order);
                    //生成销售员，代理商收益
                    SundayMember member=memberService.getById(order.getMemberId());
                    if(member.getUserType()==SundayCommonConstants.USER_TYPE_SALESMAN){
                        incomeService.updateIncome(member.getId(),order.getPayAmount(),order,SundayCommonConstants.INCOME_TYPE_BUSINESS);
                        incomeService.updateIncome(member.getAgentId(),order.getPayAmount(),order,SundayCommonConstants.INCOME_TYPE_BUSINESS);
                    }
                    if(member.getUserType()==SundayCommonConstants.USER_TYPE_MEMBER){
                        incomeService.updateIncome(member.getAgentId(),order.getPayAmount(),order,SundayCommonConstants.INCOME_TYPE_BUSINESS);
                    }

                    //memberIds.add(order.getShopId());
                }
            }

            //推送订单消息
          /*  if(ListUtil.isNotNull(memberIds)){
                List<SundayCid> cids = cidService.findByMemberId(null,memberIds);
                for(SundayCid cid:cids){
                    GeTuiUtil.sendMessage(cid,
                            "您有新的花果山果蔬订单需要配送", 1,null);
                }

            }*/

        alipayWapResult.setVerify_result(verify_result);




        return alipayWapResult;
    }
    /**
     * 微信支付回掉
     * @param request
     * @param response
     */
    public String callback_wechat(HttpServletRequest request, HttpServletResponse response)throws Exception{
        String callback_wechat_msg="success";
        //1，检验签名和请求来源
        DataInputStream in = new DataInputStream(request.getInputStream());
        byte[] dataOrigin = new byte[request.getContentLength()];
        in.readFully(dataOrigin); // 根据长度，将消息实体的内容读入字节数组dataOrigin中
        if(null != in){
            in.close(); // 关闭数据流
        }
        String wxNotifyXml = new String(dataOrigin);
        Map<String, String> params = XMLUtil.doXMLParse(wxNotifyXml);
        logger.info("00000---------weixincallbakcparam--------开始-----");
        for (String key : params.keySet()) {
            logger.info("------微信OPEN回掉返回的参数key = " + key + " and ---------value = " + params.get(key));
        }
        logger.info("00000---------weixincallbakcparam--------结束-----");
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("type",SundayCommonConstants.pay_type_wechatpay_open);
        List<SundayPayConfig> payConfigs =payConfigMapper.select(param);
        //微信API
        String wechatApi = "";
        if(ListUtil.isNull(payConfigs)){
            return "fail";
        }
        //微信API
        wechatApi=payConfigs.get(0).getWeChatApi();
        //校验签名
        boolean isSign= WXPayNotify.verifyNotify(params,wechatApi);
        logger.info("-------------------微信-open-回掉-签名校验实际结果--"+isSign);
        //2017年6月14日，零时不校验签名
        isSign=true;
        if(!isSign){
            logger.error("支付微信-open-回掉-签名验证失败。");
            return "fail";
        }
        String  trade_status=params.get("result_code");
        String  out_trade_no=params.get("out_trade_no");
        String trade_no = params.get("transaction_id");
        //微信返回的是分(金融单位)
        String  total_fee =params.get("total_fee");
        logger.info("支付-微信-open-回掉-信息.trade_status="+trade_status+
                ",out_trade_no="+out_trade_no+
                ",trade_no="+trade_no+

                ",total_fee="+total_fee
        );
        //查询本地预支付记录
        param.clear();
        if(StringUtils.isEmpty(out_trade_no)){
            logger.error("支付-微信-open-回掉-外部订单为空");
            return "fail";
        }
        param.put("orderNo",out_trade_no);
        List<SundayPay> pays = super.select(param);
        if(ListUtil.isNull(pays)){
            logger.error("支付-微信-open-回掉-本地无预支付记录，返回");
            return "fail";
        }
        SundayPay pay=pays.get(0);
        //2，项目内部逻辑。校验支付金额
        //2.1,订单消费
        //校验付款金额。微信返回的是分（金额单位）
        BigDecimal price=new BigDecimal(Double.valueOf(total_fee)/100).setScale(2,BigDecimal.ROUND_HALF_UP);

        List<Long> orderIds = new ArrayList<Long>();
            for(String orderIdStr:pay.getOrderIds().split("_")){
                orderIds.add(Long.valueOf(orderIdStr));
            }
            if(ListUtil.isNull(orderIds)){
                logger.error("支付-微信-回掉-本地预支付记录无订单参数，返回");

                return "fail";
            }
		/*	param.clear();
			param.put("status",SundayCommonConstants.ORDER_STATUS_DFK);
			param.put("ids",orderIds);
			List<KitchenOrder> orders =orderMapper.select(param);*/
            //校验付款金额。微信返回的是分（金额单位）
            Double orderPayAmount = 0.00;
            param.clear();
            param.put("ids",orderIds);
            List<MdlOrder> orders =orderMapper.select(param);
            for(MdlOrder order:orders){
                orderPayAmount+=order.getPayAmount().doubleValue();
            }
            if(price.compareTo(new BigDecimal(orderPayAmount).setScale(2,BigDecimal.ROUND_HALF_UP))==-1){
                logger.error("支付-微信-回掉-本地订单实付金额和实际回掉金额有误-此操作标识有人非法刷单，本地订单实付金额="+orderPayAmount+",微信回掉金额="+price);
                return "fail";
            }
            //更改订单状态
            List<Long> memberIds =new ArrayList<Long>();
            for(MdlOrder order:orders){

                //避免重复回掉
                if(order.getOrderStatus()==SundayCommonConstants.ORDER_STATUS_DFK){
                    logger.info("支付-微信-回掉-当前支付订单"+order.getOrderNo());

                    order.setOrderStatus(SundayCommonConstants.ORDER_STATUS_DPS);
                    order.setPayTime(new Date());
                    order.setPayNo(trade_no);
                    order.setPayType(2);
                    order.setWechatPayAmount(price);
                    orderMapper.update(order);

                    //生成销售员，代理商收益
                    SundayMember member=memberService.getById(order.getMemberId());
                    if(member.getUserType()==SundayCommonConstants.USER_TYPE_SALESMAN){
                        incomeService.updateIncome(member.getId(),order.getPayAmount(),order,SundayCommonConstants.INCOME_TYPE_BUSINESS);
                        incomeService.updateIncome(member.getAgentId(),order.getPayAmount(),order,SundayCommonConstants.INCOME_TYPE_BUSINESS);
                    }
                    if(member.getUserType()==SundayCommonConstants.USER_TYPE_MEMBER){
                        incomeService.updateIncome(member.getAgentId(),order.getPayAmount(),order,SundayCommonConstants.INCOME_TYPE_BUSINESS);
                    }
                    //memberIds.add(order.getShopId());
                }
            }
            //推送订单消息
           /* if(ListUtil.isNotNull(memberIds)){
                List<SundayCid> cids = cidService.findByMemberId(null,memberIds);
                for(SundayCid cid:cids){
                    GeTuiUtil.sendMessage(cid,
                            "您有新的花果山果蔬订单需要配送", 1,null);
                }

            }*/


        return callback_wechat_msg;
    }

}
